#include "customvideostream.h"
#include <QDebug>
#include <sys/time.h>
#include <iostream>
VideoStream::VideoStream(QObject *parent)
    : QThread(parent),
      threadState(ThreadState::Stopped),
      interruptFlag(false)
{
    avformat_network_init();
}

VideoStream::~VideoStream()
{
    close();
    avformat_network_deinit();
}

bool VideoStream::open(const QString &url)
{
    // 保证前一个实例完全停止
    if (isRunning()) {
        close();
        wait(500);
    }

    // 原子状态检查
    ThreadState expected = ThreadState::Stopped;
    if (!threadState.compare_exchange_strong(expected, ThreadState::Initializing)) {
        qWarning() << "Open failed: Stream is busy";
        return false;
    }

    currentUrl = url;
    interruptFlag.store(false);
    start();
    return true;
}

void VideoStream::close()
{
    std::cout << "****************************************videostream: "  << (int)threadState.load() << std::endl;
    if (threadState.load() == ThreadState::Stopped){
         emit sendVideoinitialized(false);
         return;
    }

    // 设置中断标志
    interruptFlag.store(true);

    // 等待线程退出
    if (isRunning()) {
        terminate();
        wait(500); // 有限等待避免死锁
    }

    // 强制状态重置
    threadState.store(ThreadState::Stopped);
    safeCleanup();
    emit sendVideoinitialized(false);
    std::cout << "***************************************close video" << std::endl;
}

void VideoStream::run()
{
    // 初始化阶段检查中断
    if (interruptFlag.load()) {
        threadState.store(ThreadState::Stopped);
        return;
    }

    // 执行初始化
    bool initSuccess = initStream();
    if (!initSuccess || interruptFlag.load()) {
        threadState.store(ThreadState::Stopped);
        emit sendVideoinitialized(false);
        return;
    }

    // 进入运行状态
    threadState.store(ThreadState::Running);
    emit sendVideoinitialized(true);

    // 主解码循环
    AVPacket packet;
    AVFrame *frame = av_frame_alloc();

    while (threadState.load() == ThreadState::Running && !interruptFlag.load()) {
        // 实时检查资源有效性
        if (!ctx.formatCtx || !ctx.codecCtx || !ctx.swsCtx) break;


        int ret = av_read_frame(ctx.formatCtx, &packet);
        if (ret < 0) {
            if (ret == AVERROR_EOF){
                 //emit frameReady(QImage());
                 //emit connectserverfailed();
                 break;
            }
            QThread::msleep(5);
            continue;
        }

        // 视频流处理
        if (packet.stream_index == ctx.videoStreamIndex) {
            if (avcodec_send_packet(ctx.codecCtx, &packet) == 0) {
                while (avcodec_receive_frame(ctx.codecCtx, frame) >= 0) {
                    QImage image = convertFrame(frame);
                    if (!image.isNull()) {
                        QMutexLocker lock(&captureMutex);
                        cachedFrame = image.copy();
                        condition.wakeAll();
                        emit frameReady(image);

                        frameCount++;
                        qint64 nowMs = QDateTime::currentMSecsSinceEpoch();
                        if (lastTimeMs == 0) {
                            lastTimeMs = nowMs;
                        } else if (nowMs - lastTimeMs >= 1000) {
                            double fps = frameCount * 1000.0 / (nowMs - lastTimeMs);
                            qDebug() << "[VideoStream] 当前FPS:" << fps;
                            emit frameRateUpdated(fps);  // 发送到UI或日志
                            lastTimeMs = nowMs;
                            frameCount = 0;
                        }
                    }
                }
            }
        }
        av_packet_unref(&packet);
        QThread::msleep(1); // 避免CPU空转
    }

    // 退出清理
    av_frame_free(&frame);
    safeCleanup();
    threadState.store(ThreadState::Stopped);
}

bool VideoStream::initStream()
{
    safeCleanup(); // 关键：确保清理旧资源

    // 验证URL有效性
    if (currentUrl.isEmpty()) {
        qCritical() << "Invalid empty URL";
        return false;
    }

    // 转换URL编码
    QByteArray urlData = currentUrl.toUtf8();
    if (urlData.isEmpty()) {
        qCritical() << "URL conversion failed";
        return false;
    }

    // 分配FormatContext
    ctx.formatCtx = avformat_alloc_context();
    std::cout << "******************************** ctx.formatCtx:" << ctx.formatCtx << std::endl;
    if (!ctx.formatCtx) {
        qCritical() << "Alloc format context failed";
        return false;
    }

    // 设置中断回调
    ctx.formatCtx->interrupt_callback.callback = [](void* ctx) {
        return static_cast<StreamContext*>(ctx)->interruptFlag.load() ? 1 : 0;
    };
    ctx.formatCtx->interrupt_callback.opaque = &ctx;

    // 设置网络参数
    AVDictionary* options = nullptr;
    av_dict_set(&options, "rtsp_transport", "udp", 0);
    av_dict_set(&options, "stimeout", "500000", 0);

    // 打开流（关键修复点）

    int ret = avformat_open_input(&ctx.formatCtx, urlData.constData(), nullptr, &options);
    av_dict_free(&options); // 立即释放选项

    if (ret != 0 || !ctx.formatCtx) {
        qCritical() << "avformat_open_input failed:" << avErrorString(ret);
        // 精确清理已分配资源
        if (ctx.formatCtx) {
            avformat_close_input(&ctx.formatCtx); // 正确释放FFmpeg内部资源
        } else {
            avformat_free_context(ctx.formatCtx); // 释放用户分配的内存
        }
        ctx.formatCtx = nullptr;
        return false;
    }

    // 获取流信息
    ret = avformat_find_stream_info(ctx.formatCtx, nullptr);
    if (ret < 0 || interruptFlag.load()) {
        qCritical() << "avformat_find_stream_info failed:" << avErrorString(ret);
        safeCleanup();
        return false;
    }

    // 查找视频流
    ctx.videoStreamIndex = av_find_best_stream(ctx.formatCtx, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);
    if (ctx.videoStreamIndex < 0) {
        qCritical() << "No video stream found";
        safeCleanup();
        return false;
    }

    // 初始化解码器
    AVCodecParameters* codecPar = ctx.formatCtx->streams[ctx.videoStreamIndex]->codecpar;
    const AVCodec* codec = avcodec_find_decoder(codecPar->codec_id);
    if (!codec) {
        qCritical() << "Codec not found";
        safeCleanup();
        return false;
    }

    ctx.codecCtx = avcodec_alloc_context3(codec);
    if (avcodec_parameters_to_context(ctx.codecCtx, codecPar) < 0) {
        qCritical() << "Init codec context failed";
        safeCleanup();
        return false;
    }

    if (avcodec_open2(ctx.codecCtx, codec, nullptr) < 0) {
        qCritical() << "Open codec failed";
        safeCleanup();
        return false;
    }

    // 验证解码器参数
    if (ctx.codecCtx->width <= 0 || ctx.codecCtx->height <= 0 || ctx.codecCtx->pix_fmt == AV_PIX_FMT_NONE) {
        qCritical() << "Invalid decoder parameters";
        safeCleanup();
        return false;
    }

    // 初始化图像转换
    ctx.swsCtx = sws_getContext(
        ctx.codecCtx->width, ctx.codecCtx->height, ctx.codecCtx->pix_fmt,
        ctx.codecCtx->width, ctx.codecCtx->height, AV_PIX_FMT_RGB32,
        SWS_FAST_BILINEAR, nullptr, nullptr, nullptr
    );
    if (!ctx.swsCtx) {
        qCritical() << "Create sws context failed";
        safeCleanup();
        return false;
    }

    emit resolutionChanged(ctx.codecCtx->width, ctx.codecCtx->height);
    return true;
}

QString VideoStream::avErrorString(int errnum)
{
    char errbuf[AV_ERROR_MAX_STRING_SIZE] = {0};
    av_strerror(errnum, errbuf, sizeof(errbuf));
    return QString::fromLocal8Bit(errbuf);
}

void VideoStream::safeCleanup()
{
    // 安全释放顺序：SWS > Codec > Format
    if (ctx.swsCtx) {
        sws_freeContext(ctx.swsCtx);
        ctx.swsCtx = nullptr;
    }

    if (ctx.codecCtx) {
        avcodec_free_context(&ctx.codecCtx);
        ctx.codecCtx = nullptr;
    }

    if (ctx.formatCtx) {
        avformat_free_context(ctx.formatCtx);
        ctx.formatCtx = nullptr;
    }

    ctx.videoStreamIndex = -1;
    interruptFlag.store(false);
}

QImage VideoStream::captureFrame()
{
    QMutexLocker locker(&captureMutex);
    if (!condition.wait(&captureMutex, 1000)) {
        return QImage();
    }
    return cachedFrame;
}

QImage VideoStream::convertFrame(AVFrame *frame) const
{
    QImage image(frame->width, frame->height, QImage::Format_RGB32);
    uint8_t *dst[] = { image.bits() };
    int dstStride[] = { static_cast<int>(image.bytesPerLine()) };

    sws_scale(ctx.swsCtx,
             frame->data, frame->linesize,
             0, frame->height,
             dst, dstStride);

    return image;
}

// VideoStream类中解码后，检查帧是否为8合1格式
bool VideoStream::is8In1Frame(const QImage &frame)
{
    return (frame.width() % 4 == 0) && (frame.height() % 2 == 0); // 简单判断，需根据实际格式调整
}
